#include <math.h>
#include <stdlib.h>
#include "report.h"

static int test_real(void)
{
  Report_Real_t stats;
  double avg, sd;
  
  Report_Real_Init(&stats);
  Report_Real_Update(&stats, 9);
  Report_Real_Update(&stats, 10);
  Report_Real_Update(&stats, 11);

  Report_Real_Update_Null(&stats);
  Report_Real_Update_Null(&stats);
  Report_Real_Update_Null(&stats);
  Report_Real_Update_Null(&stats);
  Report_Real_Update_Null(&stats);
  Report_Real_Update_Null(&stats);
  Report_Real_Update_Null(&stats);
  

  Report_Real_Compute(&stats, &avg, &sd);
  
  if (fabs(avg-10) > 1e-3)
    return 1;
  
  if (fabs(sd - sqrt((double) 2.0/3.0)) > 1e-3)
    return 2;  

  return 0;
}

static int test_naturalnum(void)
{
  Report_NaturalNum_t stats;
  int num_val;
  double * p_val_prob;
  
  Report_NaturalNum_Init(&stats);

  Report_NaturalNum_Update(&stats, 0);
  Report_NaturalNum_Update(&stats, 27);
  Report_NaturalNum_Update(&stats, 27);
  Report_NaturalNum_Update(&stats, 102);
  Report_NaturalNum_Update(&stats, 27);
  Report_NaturalNum_Update(&stats, 0);
  Report_NaturalNum_Update(&stats, 102);
  Report_NaturalNum_Update(&stats, 500);
  Report_NaturalNum_Update_Null(&stats);
  Report_NaturalNum_Update(&stats, 102);

  Report_NaturalNum_Compute(&stats, &num_val, &p_val_prob);

  if (!(num_val > 500))
    return 15;
  
  if (p_val_prob[0] != .2)
    return 16;
  
  if (p_val_prob[27] != .3)
    return 17;
  
  if (p_val_prob[102] != .3)
    return 18;

  if (p_val_prob[500] != .1)
    return 19;

  free(p_val_prob);

  Report_NaturalNum_Print(&stats);

  return 0;
}

static int test_finite(void)
{
  Report_Finite_t stats;
  int num_obj;
  double * p_obj_prob;
  
  Report_Finite_Init(&stats, 3, "Blue", "Green", "Red");

  Report_Finite_Update(&stats, 0);
  Report_Finite_Update(&stats, 0);
  Report_Finite_Update(&stats, 0);
  Report_Finite_Update(&stats, 0);
  Report_Finite_Update(&stats, 0);
  Report_Finite_Update(&stats, 1);
  Report_Finite_Update(&stats, 1);
  Report_Finite_Update(&stats, 1);
  Report_Finite_Update_Null(&stats);
  Report_Finite_Update(&stats, 2);

  Report_Finite_Compute(&stats, &num_obj, &p_obj_prob);

  if (3 != num_obj)
    return 11;
  
  if (p_obj_prob[0] != .5)
    return 12;
  
  if (p_obj_prob[1] != .3)
    return 13;
  
  if (p_obj_prob[2] != .1)
    return 14;

  free(p_obj_prob);

  Report_Finite_Print(&stats);

  return 0;
}

int main(int argc, char ** argv)
{
  int retval;
  
  if ((retval = test_real()))
    return retval;
  
  if ((retval == test_naturalnum()))
    return retval;

  if ((retval == test_finite()))
    return retval;

  return 0;
}
